/**
* @file PlayGame.cpp
* Client code to init and run the code
* @author Timmy Nelen
* @date 18/11/2010
*/

/**
 * @mainpage Nuclear Breakout: A GP project
 * @par Introduction
 * Welcome to the documentation of my breakout project for the GP course. In here you'll find documentation on the file I've used,
 * as well as lists of classes, member functions & class hierarchies.
 * @par File hierarchy
 * The hierarchy is as follow:
 * - We have a base class Entity, this is the main base class used to represent most of the games elements, we have 2 expansions to this:
 * 		- MovableEntity, used to represent entities that can move (Balls, Paddles, Powerups)
 * 		- "Non-MovableEntity" a class to represent stationary elements of the game (Breakables)
 * - On top of these classes we have the SDL representations. Abstract visualization methods are supplied in the base classes, which are overridden
 * in the SDLobjects. If you wish to build an alternative representation for the game, override these Visualization methods using the graphics engine of your choice
 * - The Game objects and the SDLGame objects are both encapsulated in respectively bo (Stands for Breakout), and bo_sdl (Breakout_SDL)
 * @par Controls
 * The controls are as follows:
 * - Use the left & right arrow keys to control the paddle
 * - Used the escape button to return to the menu screen (also pauses the game)
 * - Press escape and go to "quit" to exit the game
 * - Everything above this can also be found at the "help" screen in the game itself
 * @par Rules
 * 	- You start the game with 5 lives
 * 	- Everytime the balle exits the screen at the bottom, you lose a life
 * 	- If you lose all of your lives: It's game over
 * 	- Every ball you break is worth 10 points
 * 	- At random intervals a powerup will drop, catching this with your pedal will give you a temporary x4 speed boost on your paddle for 10 seconds, during which no powerups will fall
 * @par Runtime flags
 * 	- Thanks to the TCLAP library, multiple runtime flags are supported, being:
 * 		- --height		The height of the screen (both must be supplied if using these flags)
 * 		- --width		The width of the screen (both must be supplied if using these flags)
 * 		- --ball		The filename of the ballsprite to be used
 * 		- --paddle		The filename of the paddlesprite to be used
 * 		- --breakable	The filename of the breakablesprite to be used
 * 		- --pow			The filename of the pow sprite to be used (the image which appears when you break a ball)
 * 		- --powerup		The filename of the powerup sprite
 * 		- --bg			The filename of the background to be used
 * 		- --lives		The amount of lives you want to start off with
 * @par Comments
 *
 * 	-Implemented functionality:
 * 		- Powerups
 * 		- Multiple levels (After a level is finished the next one will automatically start, if there are multiple levels)
 * 		- Extra colission detection (If the balls happen to penetrate, they will be reset to a "barely touching" situation, so they won't look like they penetrate)
 * 		- Supporting multiple flags at runtime. An overview can be seen above, or by typing "./Breakout -h" in the terminal
 *
 *	-Unfortunately, I did not have the time (due to exams) to implement following aspects:
 * 		- Exceptions (Meaning that if you give an invalid filename as a flag, the game will crash on you without a message)
 * 		- Different types of powerups
 * 		- A completely leak-proof program. I did my best to minimize lost blocks of memory, but unfortunately it isn't perfect
 */

#define res SDLResource::Instance()

#include <iostream>
#include "../SDL/SDLResource.h"
#include "../SDL/SDLFactory.h"
#include "LevelGenerator.h"
#include "Game.h"
#include "../SDL/SDLPlayer.h"
#include <tclap/CmdLine.h>

using std::cout;
using std::endl;
using std::string;
using namespace bo_sdl;

int main(int argc, char* argv[]){
	TCLAP::CmdLine cmd("Breakout: A GP project", ' ', "1.0");
	TCLAP::ValueArg<std::string> nameArg("n","playername","The name of the player",false,"Player","string");
	TCLAP::ValueArg<int> heightArg("","height","The height of the screen",false, 600, "integer");
	TCLAP::ValueArg<int> widthArg("", "width", "The width of the screen", false, 800, "integer");
	TCLAP::ValueArg<string> ballArg("", "ball", "The filename of the ballsprite", false, "stdBall.png", "string");
	TCLAP::ValueArg<string> breakableArg("", "breakable", "The filename of the breakable sprite", false, "stdBreakable.png", "string");
	TCLAP::ValueArg<string> paddleArg("", "paddle", "The filename of the paddlesprite", false, "stdPaddle.png", "string");
	TCLAP::ValueArg<string> powArg("", "pow", "The filename of the powsprite", false, "stdPow.png", "string");
	TCLAP::ValueArg<string> powerupArg("", "powerup", "The filename of the powerup sprite", false, "stdPowerUp.png", "string");
	TCLAP::ValueArg<string> bgArg("", "bg", "The background image", false, "stdBackground.jpg", "string");
	TCLAP::ValueArg<int> livesArg("", "lives", "The ammount of lives you start off with", false, 5, "integer");
	cmd.add(livesArg);
	cmd.add(bgArg);
	cmd.add(powArg);
	cmd.add(powerupArg);
	cmd.add(paddleArg);
	cmd.add(breakableArg);
	cmd.add(ballArg);
	cmd.add(heightArg);
	cmd.add(widthArg);
	cmd.add( nameArg );
	cmd.parse( argc, argv );
	std::string name = nameArg.getValue();
	int xScreen = widthArg.getValue();
	int yScreen = heightArg.getValue();
	if ( ( (double)xScreen / (double)yScreen != 4.0/3.0 ) ){
		cout << "Wrong screen dimensions! Reverting to 800x600!" << endl;
		xScreen = 800;
		yScreen = 600;
	}
	const char* breakableFile = breakableArg.getValue().c_str();
	const char* paddleFile = paddleArg.getValue().c_str();
	const char* powerUpFile = powerupArg.getValue().c_str();
	const char* powFile = powArg.getValue().c_str();
	const char* ballFile = ballArg.getValue().c_str();
	const char* backgroundFile = bgArg.getValue().c_str();
	int lives = livesArg.getValue();
	if ( lives < 1 ){
		cout << "Error: Ammount of lives has be to larger than 0! using default value: 5 now" << endl;
		lives = 5;
	}

	// Init the screen (has to be done only once)
	double scale = xScreen/8;
	res->Initialize(xScreen, yScreen, scale, backgroundFile, powFile);
	//res->SetBackground("background.jpg");
	// Scale which every coord has to be multiplied with
	SDLFactory* fact = new SDLFactory;
	LevelGenerator* gen = new LevelGenerator(fact);
	int fps = 60;
	SDLPlayer* player = new SDLPlayer(name.c_str(), lives);
	Game* gameObj = new Game(fact, gen, fps, lives, player);
	gameObj->GenStdGame(paddleFile, ballFile, breakableFile, powFile, powerUpFile);
	//gameObj->GenStdGame("paddle.png", "ball.png", "breakablesmall.png");
	int menuOption = 1;
	while ( menuOption >= 0){
		res->ShowMenu(menuOption);
		if ( menuOption == 0 ){
			gameObj->Run(menuOption);
		}
		else if ( menuOption == 1 )
			res->ShowHelpMenu();
		else if ( menuOption == 2 )
			return 0;
	}
}

